﻿#include <objbase.h>
#include <initguid.h>
#include <imaging.h>

#include "HnrjitImaging.h"

/// <summary>应用程序目录</summary>
static TCHAR g_szAppDirPath[MAX_PATH] = { 0 };

/// <summary>图像成像工厂</summary>
static CComPtr<IImagingFactory> g_spImagingFactory;

BOOL CHnrjitImaging::ImagingInitialize()
{
	if (!g_spImagingFactory)
	{
		CoInitializeEx(0, COINIT_MULTITHREADED);
		CoCreateInstance(CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void**)&g_spImagingFactory);
	}
	return g_spImagingFactory != NULL;
}

BOOL CHnrjitImaging::ImagingUninitialize()
{
	if (g_spImagingFactory)
	{
		g_spImagingFactory = NULL;
		CoUninitialize();
	}
	return g_spImagingFactory != NULL;
}

const TCHAR* CHnrjitImaging::AppDirPath()
{
	if (g_szAppDirPath[0] == 0)
	{
		GetModuleFileName(GetModuleHandle(NULL), g_szAppDirPath, _countof(g_szAppDirPath));
		TCHAR* pcLastBackslash = _tcsrchr(g_szAppDirPath, _T('\\'));
		*pcLastBackslash = 0;
	}
	return g_szAppDirPath;
}

const TCHAR* CHnrjitImaging::Utf8ToLocal(const CHAR* pszUtf8Str, CAtlArray<TCHAR>* paResult)
{
	if (!paResult->IsEmpty()) paResult->RemoveAll();

	int cbReturn = MultiByteToWideChar(CP_UTF8, 0, pszUtf8Str, -1, NULL, 0);
	if (cbReturn > 0)
	{
		if (paResult->SetCount(cbReturn))
		{
			if (MultiByteToWideChar(CP_UTF8, 0, pszUtf8Str, -1, paResult->GetData(), cbReturn) == 0)
			{
				paResult->RemoveAll();
			}
		}
	}

	return paResult->GetCount() ? paResult->GetData() : NULL;
}

const CHAR* CHnrjitImaging::LocalToUtf8(const TCHAR* pszLocalStr, CAtlArray<CHAR>* paResult)
{
	if (!paResult->IsEmpty()) paResult->RemoveAll();

	int cbReturn = WideCharToMultiByte(CP_UTF8, 0, pszLocalStr, -1, NULL, 0, NULL, NULL);
	if (cbReturn > 0)
	{
		if (paResult->SetCount(cbReturn))
		{
			if (WideCharToMultiByte(CP_UTF8, 0, pszLocalStr, -1, paResult->GetData(), cbReturn, NULL, NULL) == 0)
			{
				paResult->RemoveAll();
			}
		}
	}

	return paResult->GetCount() ? paResult->GetData() : NULL;
}

CComPtr<IImage> CHnrjitImaging::LoadFromFile(const TCHAR* pszFilePath, HZIP hZipRes /*= NULL*/)
{
	ATLASSERT(g_spImagingFactory != NULL);
	CComPtr<IImage> spResImage = NULL;
	if (hZipRes)
	{
		int nIndex;
		ZIPENTRY ZipEntry;
		if (FindZipItem(hZipRes, pszFilePath, true, &nIndex, &ZipEntry) == ZR_OK)
		{
			HGLOBAL hGlobal = GlobalAlloc(LMEM_FIXED, ZipEntry.unc_size);
			if (hGlobal)
			{
				UnzipItem(hZipRes, nIndex, hGlobal, ZipEntry.unc_size);
				g_spImagingFactory->CreateImageFromBuffer(hGlobal, ZipEntry.unc_size, DISPOSAL_GLOBALFREE, &spResImage);
			}
		}
	}
	else
	{
		TCHAR szFilePath[MAX_PATH];
		_stprintf_s(szFilePath, _countof(szFilePath), _T("%s\\%s"), AppDirPath(), pszFilePath);
		g_spImagingFactory->CreateImageFromFile(szFilePath, &spResImage);
	}

	return spResImage;
}

HBITMAP CHnrjitImaging::CreateHBitmap(CComPtr<IImage> spImage, const SIZE& bmpSize)
{
	ATLASSERT(spImage != NULL);
	HBITMAP hNewBitmap = NULL;
	HDC hdcWindow = GetWindowDC(NULL);
	if (hdcWindow)
	{
		HDC hdcMemory = CreateCompatibleDC(hdcWindow);
		if (hdcMemory)
		{
			CRect rcGeometry;
			if (bmpSize.cx && bmpSize.cy)
			{
				rcGeometry.SetRect(0, 0, bmpSize.cx, bmpSize.cy);
			}
			else
			{
				ImageInfo ImgInfo;
				if (spImage->GetImageInfo(&ImgInfo) == S_OK)
				{
					rcGeometry.SetRect(0, 0, ImgInfo.Width, ImgInfo.Height);
				}
			}
			hNewBitmap = CreateCompatibleBitmap(hdcWindow, bmpSize.cx, bmpSize.cy);
			if (hNewBitmap)
			{
				HGDIOBJ hOldBitmap = SelectObject(hdcMemory, hNewBitmap);
				spImage->Draw(hdcMemory, rcGeometry, NULL);
			}
			DeleteDC(hdcMemory); // 可以安全删除HGDIOBJ对象
		}
		ReleaseDC(NULL, hdcWindow);
	}
	return hNewBitmap;
}
